<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  
  <meta name="generator" content="Hugo 0.98.0" />

  
  <meta name="description" content="走在通往幸福的路上">
  

  
  <link rel="apple-touch-icon" sizes="180x180" href="https://blog.v5u.win/apple-touch-icon.png">

  
  <link rel="icon" type="image/png" sizes="32x32" href="https://blog.v5u.win/favicon-32x32.png">

  
  <link rel="icon" type="image/png" sizes="16x16" href="https://blog.v5u.win/favicon-16x16.png">

  
  <link rel="manifest" href="https://blog.v5u.win/site.webmanifest">

  
  <link rel="mask-icon" href="https://blog.v5u.win/safari-pinned-tab.svg" color="">

  <meta name="msapplication-TileColor" content="">

  <meta name="theme-color" content="">

  
  <link rel="stylesheet" href="https://blog.v5u.win/css/bootstrap.min.css" />

  
  <title>Go CGO | 为吾优</title>
  

  <style>
body {
  min-width: 300px;
}

.custom-navbar {
  margin-bottom: 1em;
  height: 60px;
}

.custom-navbar a {
  display: inline-block; 
  padding: 18px 0;
  margin-right: 1em; 
  font-weight: bold; 
}

.custom-navbar a:hover,
.custom-navbar a:focus {
  text-decoration: none; 
}

@media print {
  .custom-navbar {
    display: none;
  }
}

article {
  padding-bottom: 1em;
}

img {
  max-width: 100%;
}


body {
  background-color: #fff;
}



body {
  color: #212529;
}



a {
  color: #007bff;
}



a:hover,
a:focus {
  color: #0056b3;
}



.custom-navbar {
  background-color: #212529;
}



.custom-navbar a {
  color: rgba(255,255,255,.75);
}



.custom-navbar a:hover,
.custom-navbar a:focus {
  color: rgba(255,255,255,1);
}



.container {
  max-width: 800px;
}





</style>
</head>

<body>
  <nav class="custom-navbar">
  <div class="container">
    
    <a href="/">文章</a>
    
    <a href="/tags/">标签</a>
    
    <a href="/about/">关于</a>
    
    <a href="/index.xml">RSS</a>
    
  </div>
</nav>
  
  <div class="container">
    <article>
      <h1>Go CGO</h1>
<p>[TOC]</p>
<h1 id="golang-中调用-cc-代码有三种方式">golang 中调用 c/c++ 代码有三种方式</h1>
<ul>
<li>直接<code>嵌套</code>在go文件中使用，最简单直观的</li>
<li>导入<code>动态库 .so 或 dll</code> 的形式，最安全但是很不爽也比较慢的</li>
<li>直接引用 c/c++ 文件的形式，层次分明，容易随时修改看结果的</li>
</ul>
<h2 id="需要的环境支持">需要的环境支持</h2>
<ul>
<li>Linux 具备 gcc 与 g++ 即可</li>
<li>Mac 参考 Linux</li>
<li>Windows 需要安装 <a href="https://link.juejin.im/?target=http%3A%2F%2Fwww.mingw.org%2F">mingw</a>，否则编译时会有这类错：<code>cannot find -lmingwex</code></li>
</ul>
<h2 id="嵌套">嵌套</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 嵌入式 调用
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// #include &lt;stdio.h&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// #include &lt;stdlib.h&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">void print(char *str) {
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    printf(&#34;%s\n&#34;, str);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">}
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;C&#34;</span><span style="color:#75715e">//这里可看作封装的伪包C, 这条语句要紧挨着上面的注释块，不可在它俩之间间隔空行！
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;unsafe&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">&#34;Hello Cgo&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">cs</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">C</span>.<span style="color:#a6e22e">CString</span>(<span style="color:#a6e22e">s</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">C</span>.print(<span style="color:#a6e22e">cs</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">C</span>.<span style="color:#a6e22e">free</span>(<span style="color:#a6e22e">unsafe</span>.<span style="color:#a6e22e">Pointer</span>(<span style="color:#a6e22e">cs</span>))
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">//参考来源：https://tonybai.com/2012/09/26/interoperability-between-go-and-c/
</span></span></span></code></pre></div><h2 id="调用动态链接库-so">调用动态链接库 .so</h2>
<p>目录结构</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>├── hi.c
</span></span><span style="display:flex;"><span>├── hi.go
</span></span><span style="display:flex;"><span>├── hi.h
</span></span><span style="display:flex;"><span>├── hi.o
</span></span><span style="display:flex;"><span>└── libhi.so
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">// hi.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">hi</span>() {
</span></span><span style="display:flex;"><span>    printf(<span style="color:#e6db74">&#34;Hello Cgo!</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">hi</span>(); <span style="color:#75715e">// file: hi.h
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// so 动态链接库调用
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// 参考 https://studygolang.com/articles/10163
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#cgo CFLAGS: -I./
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#cgo LDFLAGS: -L./ -lhi
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include &#34;hi.h&#34; //非标准c头文件，所以用引号
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;C&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">C</span>.<span style="color:#a6e22e">hi</span>()
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">&#34;Hi, vim-go&#34;</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 注：LDFLAGS 路径问题并未测试通过
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// CFLAGS: -I路径 这句话指明头文件所在路径
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// LDFLAGS: -L路径 -l名字 指明动态库的所在路径，-Llib -lhi，指明在 lib 下面以及它的名字 hi
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e"># 编译生成 .so 动态库</span>
</span></span><span style="display:flex;"><span>gcc hi.c -fPIC -shared -o libhi.so
</span></span></code></pre></div><h2 id="直接引用-cc-文件的形式">直接引用 c/c++ 文件的形式</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>.
</span></span><span style="display:flex;"><span>├── main.go
</span></span><span style="display:flex;"><span>└── util
</span></span><span style="display:flex;"><span>    ├── util.go
</span></span><span style="display:flex;"><span>    └── utilc
</span></span><span style="display:flex;"><span>        ├── util.c
</span></span><span style="display:flex;"><span>        └── util.h
</span></span></code></pre></div><p>目录结构</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#75715e">// util.go
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#f92672">package</span> <span style="color:#a6e22e">util</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/*
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include &#34;utilc/util.c&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;C&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">GoSum</span>(<span style="color:#a6e22e">a</span>, <span style="color:#a6e22e">b</span> <span style="color:#66d9ef">int</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">C</span>.<span style="color:#a6e22e">sum</span>(<span style="color:#a6e22e">C</span>.int(<span style="color:#a6e22e">a</span>), <span style="color:#a6e22e">C</span>.int(<span style="color:#a6e22e">b</span>))
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">s</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#75715e">// main.go
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// cgo 直接引用 c/c++ 文件的形式
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// 测试通过, .c .h 文件不能和 .go 文件在同一个目录下
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> (
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;github.com/xxx/util&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">util</span>.<span style="color:#a6e22e">GoSum</span>(<span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">5</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">// utilc/util.c
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;util.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">sum</span>(<span style="color:#66d9ef">int</span> a,<span style="color:#66d9ef">int</span> b){
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> (a<span style="color:#f92672">+</span>b);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">sum</span>(<span style="color:#66d9ef">int</span> a,<span style="color:#66d9ef">int</span> b);<span style="color:#75715e">// utilc/util.h
</span></span></span></code></pre></div><p>直接运行<code>go run main.go</code></p>
<h2 id="注意事项">注意事项</h2>
<ul>
<li>但凡要引用与 c/c++ 相关的内容，写到 go 文件的头部<code>注释</code>里面</li>
<li>嵌套的 c/c++ 代码必须符合其语法，不与 go 一样</li>
<li><code>import &quot;C&quot;</code> 这句话要紧随，注释后，不要换行，否则报错</li>
<li>go 代码中调用 c/c++ 的格式是: <code>C.xxx()</code>，例如 C.add(2, 1)</li>
</ul>
<hr>
<p><code>CFLAGS: -I路径</code> 这句话指明头文件所在路径，-Iinclude 指明 当前项目根目录的 include 文件夹</p>
<p><code>LDFLAGS: -L路径 -l名字</code> 指明动态库的所在路径，-Llib -llibvideo，指明在 lib 目录下面以及它的名字 video</p>
<p>注：此处的 LDFLAGS 更改动态库的路径后，-L指明路径，无法验证通过</p>

    </article>
  </div>

  
  
  

  
</body>

</html>